package ru.kest.torrentwatchlist.web.transform;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import ru.kest.torrentwatchlist.entity.Movie;
import ru.kest.torrentwatchlist.entity.Torrent;
import ru.kest.torrentwatchlist.web.imdb.ImdbBean;
import ru.kest.torrentwatchlist.web.imdb.ImdbService;
import ru.kest.torrentwatchlist.web.model.MovieBean;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;

/**
 * Created by Konstantin on 09.12.2014.
 */
@Component
public class MoviesTransformer {

    private class TransformMovieTask implements Callable<MovieBean> {

        private Movie dbMovie;

        public TransformMovieTask(Movie dbMovie) {
            this.dbMovie = dbMovie;
        }

        @Override
        public MovieBean call() throws Exception {
            logger.info(Thread.currentThread().getName() + " transform movie " + dbMovie.getNameFull());
            return transformMovie(dbMovie);
        }
    }

    @Autowired
    TorrentTransformer torrentTransformer;

    @Autowired
    ImdbService imdbService;

//    private ExecutorService executorService = Executors.newFixedThreadPool(8);
//    private ExecutorService executorService = Executors.newSingleThreadExecutor();
    private ExecutorService executorService = Executors.newCachedThreadPool();

    private static Logger logger = Logger.getLogger("MoviesTransformer");

    public List<MovieBean> transformMovies(List<Movie> dbMovies) {
        List<Future<MovieBean>> futures = new ArrayList<>();
        List<MovieBean> result = new ArrayList<>();

        for (Movie dbMovie : dbMovies) {
            Callable<MovieBean> callable = new TransformMovieTask(dbMovie);
            Future<MovieBean> future = executorService.submit(callable);
            futures.add(future);
        }
        for (Future<MovieBean> future : futures) {
            try {
                result.add(future.get());
            } catch (InterruptedException | ExecutionException e) {
                logger.error(e.getMessage(), e);
            }
        }

        return result;
    }

    public MovieBean transformMovie(Movie dbMovie) {
        MovieBean result = new MovieBean();

        result.setId(dbMovie.getId());
        result.setNameFull(dbMovie.getNameFull());
        result.setDescription(dbMovie.getDescription());
        result.setGenre(dbMovie.getGenre());
        result.setFavorites(dbMovie.isFavorites());
        result.setPosterUrl(dbMovie.getPosterUrl());
        result.setYear(dbMovie.getYear());

        result.setNew(isMovieNew(dbMovie.getViewingDate()));
        result.setTranslation(getTranslation(dbMovie.getTorrents()));
        result.setImdbId(dbMovie.getImdbId());
        // TO-DO temporary disabled
        result.setImdbRating(getImdbRating(dbMovie.getImdbId()));
//        result.setImdbRating("1.0");

        result.setTorrents(torrentTransformer.transformTorrents(dbMovie.getTorrents()));
        return result;
    }

    private String getImdbRating(String id) {
        ImdbBean rating = imdbService.getRating(id);

        return rating.getImdbRating();
    }

    private boolean isMovieNew(Date lastViewingDate) {
        LocalDateTime now = LocalDateTime.now();
        Instant instant = Instant.ofEpochMilli(lastViewingDate.getTime());
        LocalDateTime viewingDate = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());

        long hours = ChronoUnit.HOURS.between(viewingDate, now);

        return hours <= 18;
    }

    private String getTranslation(List<Torrent> torrents) {
        String result = null;
        for (Torrent torrent : torrents) {
            String trans = torrent.getTranslation();
            if (!StringUtils.isEmpty(trans)) {
                if (trans.toUpperCase().contains("ДУБЛ")) {
                    return trans;
                }
                result = trans;
            }
        }
        return result;
    }
}
